home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / tec-vector-src.lha / 4bp_vector.S next >
Text File  |  1994-09-24  |  19KB  |  612 lines

  1. *    This program is free software; you can redistribute it and/or modify
  2. *    it under the terms of the GNU General Public License as published by
  3. *    the Free Software Foundation; either version 2 of the License, or
  4. *    (at your option) any later version.
  5. *
  6. *    This program is distributed in the hope that it will be useful,
  7. *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9. *    GNU General Public License for more details.
  10. *
  11. *    You should have received a copy of the GNU General Public License
  12. *    along with this program; if not, write to the Free Software
  13. *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. *
  15. *************************************************************************
  16.  
  17. *************************************************************************
  18. * 4 Bp Concave Multicoloured Lightsource-shaded Filled Animated Vectors *
  19. * ©1989-1991 Steinar Midtskogen  Last updated: 13:30:31 9th August 1991 *
  20. *************************************************************************
  21.  
  22.     Include    df0:Include/Hardware/FastBlit.i
  23.     Auto    e\j
  24.  
  25.     >Extern    "RAM:8bitSine",sinetab
  26.     >Extern    "RAM:NewComb",colcomb
  27.  
  28. ******************************** CONSTANTS ******************************
  29. Height=    240                ; X=[2..280], even numbers only.
  30. Width=    22*16                ; X=[16..352], X/16=N.
  31.  
  32. ********************************* MACROS ********************************
  33. Clip:    Macro
  34.     move.w    (a0)+,d4        ; * This macro is used to clip
  35.     cmp.w    \1,d4            ;   lines.
  36.     b\6.s    skip\@            ;
  37.     sub.w    \2,d4            ;
  38.     b\3    return            ;
  39.     sub.w    \2,\1            ;
  40.     sub.w    \4,\5            ;
  41.     muls    d4,\5            ;
  42.     divs    \1,\5            ;
  43.     move.w    -2(a0),\1        ;
  44.     add.w    \4,\5            ;
  45. \7    move.w    d3,(a1)+
  46. skip\@:
  47.     EndM
  48.  
  49. GetXYZ:    Macro
  50. fake\@:    move.w    (a3)+,d5        ; * Read value from the connect-
  51.     add.w    d5,d5            ;   array and multiply by two.
  52.     bpl.s    real\@            ; * Is it an invisible point? 
  53.     neg.w    d5            ;
  54.     cmp.w    0(a2,d5.w),a6        ; * Is the Z-value of this point
  55.     ble.s    fake\@            ;   less than the other Z-values.
  56.     move.w    0(a2,d5.w),a6        ;   If yes, store Z-value.
  57.     cmp.w    #0,a6            ; * Avoid removing surface
  58.     bpl.s    fake\@            ;   because of invisible point.
  59.     lea    1.w,a6            ;
  60.     bra.s    fake\@            ; * It's invisible, jump back.
  61. real\@:    cmp.w    0(a2,d5.w),a6        ; * Is the Z-value of this point
  62.     ble.s    stay\@            ;   less than the other Z-values.
  63.     move.w    0(a2,d5.w),a6        ;   If yes, store Z-value.
  64. stay\@:    add.w    d5,d5            ; * Copy X,Y-values to \1 & \2.
  65.     move.w    0(a4,d5.w),\1        ;
  66.     move.w    2(a4,d5.w),\2        ;  
  67.     EndM
  68.  
  69. MatRot:    Macro
  70. \7    move.w    \1,\4            ;
  71. \7    move.w    \2,\5            ;
  72. \7    move.w    \3,\6            ;
  73.     muls    (a1)+,\1        ; * Multiply X, Y & Z by values
  74.     muls    (a1)+,\2        ;   in the matrix.
  75.     muls    (a1)+,\3        ;
  76.     add.l    \2,\1            ; * Add all results.
  77.     add.l    \3,\1            ;
  78.     swap    \1            ; * Correct size.
  79.     EndM
  80.  
  81. WaitBlt:Macro
  82. wbl\@:    btst    #6,DmaConr(a6)        ; * Wait for blitter to finish.
  83.     bne.s    wbl\@            ;
  84.     EndM
  85.  
  86.     jmp    start            ; * Start vector.
  87.  
  88.     SECTION    data,DATA_C
  89. copper1:dc.w $008e,$aa00-[Height/2*$100]+$71
  90.     dc.w $0090,[$aa00+[Height/2*$100]+$d1]&$ffff
  91.     dc.l $00920030,$009400d8,$008a0000
  92. copper2:dc.l $00e00007,$00e20000,$00e40007,$00e6002c
  93.     dc.l $00e80007,$00ea0058,$00ec0007,$00ee0084
  94.     dc.w $0180,$0000,$a909-[Height/2*$100],$fffe,$0180,$0555
  95.     dc.l $01820112,$01840334,$01860557,$01880779,$018a099c
  96.     dc.l $018c0010,$018e0130,$01900250,$01920471,$019406b2,$01960200
  97.     dc.l $01980400,$019a0600,$019c0901,$019e0c02
  98.     dc.l $01080084,$010a0084,$01020000,$01004200,$009c8010
  99.     dc.w $aa09-[Height/2*$100],$fffe,$0180,$0004
  100.     IF Height>171 THEN
  101.      dc.l $ffe1fffe
  102.     EndIf
  103.     dc.w [$aa09+[Height/2*$100]]&$ffff,$fffe,$0180,$0555
  104.     IF Height=170 THEN
  105.      dc.l $ffe1fffe
  106.     EndIf
  107.     dc.w [$ab09+[Height/2*$100]]&$ffff,$fffe,$0180,$0003
  108.     dc.l $01800000,$01000204,$fffffffe
  109.  
  110.     SECTION graphics,BSS_C
  111. frame1:    ds.b    Height*44*4
  112. frame2:    ds.b    Height*44*4
  113. workscr:ds.b    Height*44
  114. stencil:ds.b    [Height+2]*44
  115.  
  116.     SECTION    code,CODE
  117. ******* MASK & PERSPECTIVE GENERATION AND COPPER & INTERRUPT SETUP ******
  118. start:    movem.l    d0-d7/a0-a6,-(SP)    ; * Store all registers.
  119.     lea    prspect,a0        ; * This loop makes a $1fd8 words
  120.     move.w    #320,d0            ;   long array with $a00000/X,
  121.     move.w    #$1fd7,d3        ;   X = [320,328,336 ...]
  122. psploop:move.l    #$a00000,d1        ;
  123.     divu    d0,d1            ;
  124.     move.w    d1,(a0)+        ;
  125.     addq.w    #8,d0            ;
  126.     dbf    d3,psploop        ;
  127.     lea    stencil,a0        ; * This 2-dimensional loop makes
  128.     move.w    #Height/2,d1        ;   the mask needed for colour-
  129. msklop1:moveq    #10,d0            ;   mixing.
  130. msklop2:move.l    #$55555555,(a0)+    ;
  131.     move.l    #$aaaaaaaa,40(a0)    ;
  132.     dbf    d0,msklop2        ;
  133.     lea    44(a0),a0        ;
  134.     dbf    d1,msklop1        ;
  135.     move.w    $dff01c,-(SP)        ; * Start copper and interrupt.
  136.     bset    #15,(SP)        ;
  137.     move.w    #$7fff,$dff096        ;
  138.     clr.l    $dff144            ;
  139.     move.w    #$87c0,$dff096        ;
  140.     move.w    #$3fff,$dff09a        ;
  141.     move.l    $6c.w,-(SP)        ;
  142.     move.l    #interpt,$6c.w        ;
  143.     move.w    #$8010,$dff09a        ;
  144.     move.l    #copper1,$dff080    ;
  145.     move.l    #copper2,$dff084    ;
  146.     clr.w    $dff088            ;
  147. notquit:bsr    program            ; * Bsr to the main program.
  148.     Waitblt                ; * Waitblit.
  149. waitrst:cmp.w    #$ae00,VhPosr(a6)    ; * Wait for safe point.
  150.     blo.s    waitrst            ;
  151.     move.w    copper2+2,BltDpth(a6)    ; * Start the blitter to clear
  152.     move.w    copper2+6,BltDptl(a6)    ;   the screen.
  153.     move.l    #$1000000,BltCon0(a6)    ;
  154.     clr.w    BltDmod(a6)        ;
  155.     move.w    #Height*128+44,(a6)    ;
  156.     btst    #6,$bfe001        ; * Jump back to raster if left
  157.     bne.s    notquit            ;   mousebutton is not pressed.
  158.     move.l    $4.w,a0            ; * Restore copperlist 1.
  159.     move.l    156(a0),a0        ;
  160.     move.l    38(a0),$dff080        ;
  161.     move.l    (SP)+,$6c.w        ; * Reset copper and interrupt-
  162.     move.w    #$7fff,IntEna(a6)    ;   vectors.
  163.     move.w    (SP)+,IntEna(a6)    ;
  164.     movem.l    (SP)+,d0-d7/a0-a6    ; * Reset registers.
  165.     rts
  166. sinetab:blk.b    2560,0
  167. colcomb:blk.b    3072,0
  168.  
  169. ******************************** INTERRUPT ******************************
  170. interpt:btst    #10,$dff058+PotGor    ; * Rotation halted? 
  171.     beq.s    rothalt            ;
  172.     add.w    #3*2,regist1+2        ; * Add to angles.
  173.     add.w    #2*2,regist1+6        ;
  174.     add.w    #2*2,regist1+10        ;
  175.     and.w    #$7fe,regist1+2        ;
  176.     and.w    #$7fe,regist1+6        ;
  177.     and.w    #$7fe,regist1+10    ;
  178. rothalt:bsr.s    animate            ; * Animation.
  179.     move.w    #16,$dff058+IntReq    ;
  180.     rte
  181.  
  182. ******************************** ANIMATION ******************************
  183. animate:movem.l    d0-d1/a0-a2,-(SP)    ; * Store used registers.
  184.     lea    anim(PC),a0        ; * Start-address of the
  185. nxtanim:tst.w    (a0)            ;   animation data.
  186.     bmi.s    animfin            ; * No more points to animate?
  187.     subq.w    #1,(a0)+        ; * Decrement counter.
  188.     bmi.s    movepnt            ; * Time for movement?
  189.     addq.l    #8,a0            ; * Not yet, skip to next point.
  190.     move.w    -2(a0),d0        ;
  191.     mulu    #6,d0            ;
  192.     add.l    d0,a0            ;
  193.     bra.s    nxtanim            ;
  194. movepnt:move.w    (a0)+,-4(a0)        ; * It's time for movement; which
  195.     lea    data_3d(PC),a1        ;   point?
  196.     move.w    (a0)+,d0        ;
  197.     mulu    #6,d0            ;
  198.     add.l    d0,a1            ;
  199.     addq.w    #1,(a0)            ; * Increase counter.
  200.     move.w    (a0)+,d1        ; * Counter>max value?
  201.     cmp.w    (a0),d1            ;
  202.     bne.s    notexhd            ;
  203.     moveq    #0,d1            ;
  204.     clr.w    -2(a0)            ;
  205. notexhd:move.w    (a0)+,d0        ; * Move point to next position.
  206.     mulu    #6,d0            ;
  207.     move.l    a0,a2            ;
  208.     add.l    d0,a2            ;
  209.     mulu    #6,d1            ;
  210.     add.l    d1,a0            ;
  211.     move.w    (a0)+,(a1)+        ;
  212.     move.w    (a0)+,(a1)+        ;
  213.     move.w    (a0),(a1)        ;
  214.     move.l    a2,a0            ;
  215.     bra.s    nxtanim            ; * Move next points if any.
  216. animfin:movem.l    (SP)+,d0-d1/a0-a2    ; * Restore used registers.
  217.     rts                ;
  218.  
  219. ************************ SWAP SCREENS, READ MOUSE ***********************
  220. program:lea    frame2,a0        ; * Address of first frame.
  221.     lea    copper2+2,a1        ;
  222.     moveq    #3,d1            ;
  223.     move.l    #frame1+44*4*[Height/2-1]-2,regist4+16
  224.     eor.w    #1,regist4+20        ; * 0->1, 1->0.
  225.     beq.s    firstf            ;
  226.     move.l    #frame2+44*4*[Height/2-1]-2,regist4+16
  227.     lea    frame1,a0        ; * Address of second frame.
  228. firstf:    move.l    a0,d0            ; * Move address to copperlist.
  229.     swap    d0            ;
  230.     move.w    d0,(a1)            ;
  231.     move.w    a0,4(a1)        ;
  232.     lea    44(a0),a0        ;
  233.     addq.l    #8,a1            ;
  234.     dbf    d1,firstf        ;
  235. bug:    movem.l    regist1(PC),d6-d7/a0-a6    ; * Copy regist1.
  236.     move.w    Joy0dat(a6),d0        ; * Read XY-value of mouse, 
  237.     not.w    d0            ;   reverse it,
  238.     lsr.w    #2,d0            ;   Y=Y/4,
  239.     sub.w    #512,d0            ;   subract 512 &
  240.     move.w    d0,regist2+26        ;   store it.
  241.  
  242. *********************** COMPUTE THE ROTATION-MATRIX *********************
  243.     move.w    0(a1,d7.w),d1        ; * X1=CosY*CosZ.
  244.     move.w    0(a2,d7.w),d3        ;   Y1=SinZ*CosY.
  245.     move.w    0(a1,a0.w),d4        ;   Z1=-SinY.
  246.     move.w    0(a2,a0.w),d5        ;
  247.     move.w    d4,d2            ;
  248.     move.w    d3,d0            ;
  249.     muls    d3,d2            ;
  250.     muls    d5,d0            ;
  251.     move.w    d2,6(a4)        ;
  252.     move.w    d1,d2            ;
  253.     asl.w    #4,d2            ;
  254.     neg.w    d2            ;
  255.     move.w    d2,12(a4)        ;
  256.     move.w    d0,(a4)+        ;
  257.     move.w    0(a1,d6.w),d0        ; * X2=SinX*SinY*CosZ-CosX*SinZ.
  258.     muls    d0,d1            ;   Y2=SinX*SinY*SinZ+CosX*CosZ.
  259.     muls    d3,d0            ;   Z2=SinX*CosY.
  260.     asr.l    #7,d1            ;
  261.     move.w    d1,d2            ;
  262.     muls    0(a2,a0.w),d1        ;
  263.     muls    0(a2,d6.w),d4        ;
  264.     sub.w    d4,d1            ;
  265.     muls    0(a1,a0.w),d2        ;
  266.     muls    0(a2,d6.w),d5        ;
  267.     add.w    d5,d2            ;
  268.     asr.w    #3,d0            ;
  269.     move.w    d0,12(a4)        ;
  270.     move.w    d2,6(a4)        ;
  271.     move.w    d1,(a4)+        ;
  272.     move.w    0(a1,d7.w),d0        ; * X3=SinY*CosX*CosZ+SinX*SinZ.
  273.     muls    0(a2,d6.w),d0        ;   Y3=SinY*CosX*SinZ-SINX*CosZ.
  274.     move.w    0(a2,d7.w),d3        ;   Z3=CosX*CosY.
  275.     muls    0(a2,d6.w),d3        ;
  276.     asr.l    #7,d0            ;
  277.     move.w    d0,d2            ;
  278.     muls    0(a2,a0.w),d2        ;
  279.     muls    0(a1,a0.w),d0        ;
  280.     move.w    0(a1,d6.w),d1        ;
  281.     move.w    d1,d4            ;
  282.     muls    0(a1,a0.w),d1        ;
  283.     add.w    d1,d2            ;
  284.     muls    0(a2,a0.w),d4        ;
  285.     sub.w    d4,d0            ;
  286.     asr.w    #3,d3            ;
  287.     move.w    d3,12(a4)        ;
  288.     move.w    d0,6(a4)        ;
  289.     move.w    d2,(a4)            ;
  290.  
  291. *********** ROTATE POINTS AND CONVERT TO 2D AND STORE X, Y & Z **********
  292.     move.w    #$0010,$dff09a        ; * No interrupt while computing.
  293.     move.w    points(PC),d7        ; * Number of points to rotate.
  294.     movem.l    regist2(PC),a0-a6    ; * Copy regist2.
  295. compute:movem.w    (a5)+,d0/d2/d3        ; * Read point(X,Y,Z) to rotate.
  296.     MatRot    d0,d2,d3,d1,d4,d5    ; * Rotate point.
  297.     MatRot    d1,d4,d5,d2,d3,d6    ;
  298.     MatRot    d2,d3,d6,*,*,*,*    ;
  299.     lea    -18(a1),a1        ;
  300.     add.w    xpos(PC),d0        ; * Move object to a position.
  301.     add.w    a3,d1            ;
  302.     movem.w    d0-d2,(a2)        ; * Store XYZ before 3d->2d.
  303.     addq.l    #8,a2            ;
  304.     add.w    a6,d2            ;
  305.     and.w    #-2,d2            ; * 3 dimensions -> 2 dimensions.
  306.     move.w    prspect(PC,d2.w),d3    ;
  307.     muls    d3,d0            ;
  308.     muls    d3,d1            ;
  309.     swap    d1            ;
  310.     move.w    d1,d0            ;
  311.     move.l    d0,(a4)+        ; * Store X,Y in data_2d.
  312.     move.w    d2,(a0)+        ; * Store Z in surfcz1.
  313.     dbf    d7,compute        ; * Repeat until finished.
  314.     move.w    #$8010,$dff09a        ; * Enable interrupt.
  315.     bra    findvis            ;
  316. prspect:blk.w    $2100,0
  317. xpos:    dc.w    0
  318.  
  319. ************ FIND VISIBLE SURFACES AND THEIR START-ADDRESSES ************
  320. findvis:move.l    #sizes-2,adds        ;
  321.     movem.l    regist3(PC),a0-a5    ; * Copy regist3.
  322.     move.w    #-1,-(SP)        ; * Surfaces=-1.
  323. addsurf:addq.w    #1,(SP)            ; * Surfaces=surfaces+1.
  324. newsurf:addq.l    #2,adds            ;
  325.     move.w    #$fe,d7            ;
  326.     move.l    a0,adds+4        ;
  327.     move.b    (a3)+,(a0)        ; * Move colour to lines.
  328.     bmi    drawsur            ; * No more surfaces?
  329.     add.b    (a3)+,d7        ; * Read command from connect.
  330.     lea    $7fff.w,a6        ; * Move max-value to a6.
  331.     GetXYZ    d0,d1            ; * Get 3 Xs & Ys and test Zs.
  332.     GetXYZ    d2,d3            ;
  333.     GetXYZ    d4,d5            ;
  334.     movem.w    d0-d5,2(a0)        ; * Copy three points.
  335.     sub.w    d0,d2            ; * Is surface is visible?
  336.     sub.w    d1,d3            ;
  337.     sub.w    d0,d4            ;
  338.     sub.w    d1,d5            ;
  339.     muls    d3,d4            ;
  340.     muls    d2,d5            ;
  341.     sub.l    d5,d4            ;
  342.     blt.s    visible            ; * Branch if visible.
  343.     add.w    d7,d7            ;
  344.     add.w    d7,a3            ; * Not visible, new surface.
  345.     bra    newsurf            ;
  346. visible:movem.w    -6(a3),d0-d2        ; * Get the first three points.
  347.     move.l    a0,(a1)+        ; * Surface is visible;
  348.     lea    14(a0),a0        ;   store address of surface.
  349.     dbf    d7,cpyrest        ; * Three points already copied.
  350.     bra.s    endofsf            ;   Was that all?
  351. cpyrest:GetXYZ    (a0)+,(a0)+        ;   If no, copy the rest.
  352.     dbf    d7,cpyrest        ;
  353. endofsf:move.w    #$8000,(a0)+        ; * Set end-mark.
  354.     move.w    a6,(a5)+        ; * Store the lowest Z-value.
  355.     bgt    shading            ;   Was it <=0? If no, jump.
  356.     subq.w    #4,a1            ; * Negative Z-values, delete
  357.     subq.w    #2,a5            ;   surface.
  358.     bra    newsurf            ; * Jump back.
  359.  
  360. ****************************** SHADE SURFACE ****************************
  361. shading:lsl.w    #3,d0            ; * Get X, Y & Z-values of the
  362.     lsl.w    #3,d1            ;   three first points.
  363.     lsl.w    #3,d2            ;
  364.     movem.w    rot_3d(PC,d0.w),d6-d7/a6;
  365.     movem.w    rot_3d(PC,d2.w),d3-d5    ;
  366.     movem.w    rot_3d(PC,d1.w),d0-d2    ;
  367.     sub.w    d6,d0            ; d0=X2-X1
  368.     sub.w    d7,d1            ; d1=Y2-Y1
  369.     sub.w    a6,d2            ; d2=Z2-Z1
  370.     sub.w    d6,d3            ; d3=X3-X1
  371.     sub.w    d7,d4            ; d4=Y3-Y1
  372.     sub.w    a6,d5            ; d5=Z3-Y1
  373.     move.w    d5,d7            ; * (Z3-Z1)(Y2-Y1)-(Y3-Y1)(Z2-Z1)
  374.     muls    d1,d7            ;
  375.     move.w    d4,d6            ;
  376.     muls    d2,d6            ;
  377.     sub.l    d6,d7            ;
  378.     move.w    d3,d6            ; * (X3-X1)(Z2-Z1)-(Z3-Z1)(X2-X1)
  379.     muls    d2,d6            ;
  380.     muls    d0,d5            ;
  381.     sub.l    d5,d6            ;
  382.     muls    d0,d4            ; * (Y3-Y1)(X2-X1)-(X3-X1)(Y2-Y1)
  383.     muls    d1,d3            ;
  384.     sub.l    d3,d4            ;
  385.     asr.l    #8,d7            ; * Correct sizes.
  386.     asr.l    #8,d6            ;
  387.     swap    d4            ;
  388.     rol.l    #6,d4            ;
  389.     movem.w    ezvec(PC),d0-d2        ;
  390.     muls    d0,d7            ; * Multiply results by light-
  391.     muls    d1,d6            ;   vector.
  392.     muls    d2,d4            ;
  393.     add.l    d6,d7            ; * Average values.
  394.     add.l    d4,d7            ;
  395.     asr.l    #3,d7            ; * Correct size.
  396.     move.l    adds(PC),a6        ;
  397.     divs    (a6),d7            ;
  398.     bpl.s    notdark            ; * Get correct colour.
  399.     moveq    #0,d7            ;
  400. notdark:move.l    adds+4(PC),a6        ;
  401.     move.w    (a6),d4            ;
  402.     and.w    #$700,d4        ;
  403.     add.w    d4,d4            ;
  404.     lsl.w    #5,d7            ;
  405.     add.w    d7,d4            ;
  406.     move.w    d4,(a6)            ;
  407.     bra    addsurf            ;
  408. rot_3d:    blk.w    1024,0
  409.  
  410. *********** DRAW THE MOST DISTANT SURFACE ON THE WORKSCREEN *************
  411. drawsur:move.w    (SP),d7            ; * Number of surfaces to draw.
  412.     movem.l    regist4(PC),a1/a3-a4/a6    ; * Copy regist4.
  413. nxtsurf:moveq    #0,d6            ; * Set d6 to min-value.
  414.     move.w    (SP),d3            ; * Number of surfaces.
  415.     lea    surfcz2(PC),a0        ; * Load some registers.
  416.     lea    colcomb-512(PC),a5    ;
  417.     dbf    d7,drawlns        ; * Surfaces=surfaces-1.
  418.     addq.l    #2,SP            ; * Restore stackpointer.
  419.     rts                ; * Finished.
  420. drawlns:move.w    d3,d4            ;
  421. fndmdst:cmp.w    (a0)+,d6        ; * Z-value lower than d6?
  422.     bge.s    zlower            ; * If yes, branch to zlower.
  423.     move.w    -2(a0),d6        ; * If no, copy Z-value to d6
  424.     move.w    d3,d5            ; * Move counter to d5.
  425. zlower:    dbf    d3,fndmdst        ; * Continue searching.
  426.     sub.w    d5,d4            ; * Find address of the address
  427.     add.w    d4,d4            ;   of the surface to draw, and
  428.     clr.w    0(a4,d4.w)        ;   delete the Z-value from
  429.     add.w    d4,d4            ;   surfcz2.
  430.     move.l    0(a3,d4.w),a2        ;
  431.     pea    $80008000        ; * Set the area to max.
  432.     pea    $7fff7fff        ;
  433.     move.w    #44,BltCmod(a6)        ; * Set some constant blitter-
  434.     move.l    #-$8000,BltBdat(a6)    ;   values.
  435.     move.w    #7,BltCpth(a6)        ;
  436.     add.w    (a2)+,a5        ; * Get the colour-combination.
  437. nxtline:movem.w    (a2),d0-d3        ; * Get (X1,Y1) & (X2,Y2).
  438.     addq.l    #4,a2            ;
  439.     pea    drawfin(PC)        ;
  440. draw:    lea    screen(PC),a0        ;
  441.     cmp.w    d0,d2            ; * X1<X2.
  442.     bgt.s    exchg1            ;
  443.     exg    d0,d2            ;
  444.     exg    d1,d3            ;
  445. exchg1:    Clip    d0,d2,pl,d3,d1,lt,*    ; * Clip lines (left edge).
  446.     Clip    d2,d0,mi,d1,d3,ge    ; * Clip lines (right edge).
  447.     add.w    #176,d0            ; * Move origo.
  448.     add.w    #176,d2            ;
  449.     cmp.w    4(SP),d0        ; * Find smallest X (area).
  450.     bge.s    area1            ;
  451.     move.w    d0,4(SP)        ;
  452. area1:    cmp.w    8(SP),d2        ; * Find largest X (area).
  453.     ble.s    area2            ;
  454.     move.w    d2,8(SP)        ;
  455. area2:    cmp.w    d1,d3            ; * Y1<Y2.
  456.     beq    return            ; * DeltaY=0?
  457.     bgt.s    exchg2            ;
  458.     exg    d0,d2            ;
  459.     exg    d1,d3            ;
  460. exchg2:    Clip    d1,d3,pl,d2,d0,lt,*    ; * Clip lines (upper edge).
  461.     Clip    d3,d1,le,d0,d2,ge,*    ; * Clip lines (lower edge).
  462.     cmp.w    6(SP),d1        ; * Find smallest Y (area).
  463.     bge.s    area3            ;
  464.     move.w    d1,6(SP)        ;
  465. area3:    cmp.w    10(SP),d3        ; * Find largest Y (area).
  466.     ble.s    area4            ;
  467.     move.w    d3,10(SP)        ;
  468. area4:    move.w    d1,d4            ; * Find octant.
  469.     muls    #44,d4            ;
  470.     move.w    d0,d5            ;
  471.     asr.w    #3,d5            ;
  472.     ext.l    d5            ;
  473.     add.l    #workscr+44*[Height/2],d4
  474.     add.l    d5,d4            ;
  475.     moveq    #0,d5            ;
  476.     sub.w    d1,d3            ;
  477.     sub.w    d0,d2            ;
  478.     bpl.s    fnddx            ;
  479.     moveq    #1,d5            ;
  480.     neg.w    d2            ;
  481. fnddx:    move.w    d3,d1            ;   Fix corner.
  482.     add.w    d1,d1            ;
  483.     cmp.w    d2,d1            ;
  484.     dbhi    d3,fixcrn        ;
  485. fixcrn:    move.w    d3,d1            ;
  486.     sub.w    d2,d1            ;
  487.     bpl.s    dygdx            ;
  488.     exg    d2,d3            ;
  489. dygdx:    addx.w    d5,d5            ;
  490.     add.w    d2,d2            ;
  491.     move.w    d2,d1            ;
  492.     sub.w    d3,d2            ;
  493.     addx.w    d5,d5            ;
  494.     and.w    #$f,d0            ;
  495.     ror.w    #4,d0            ;
  496.     or.w    #$a4a,d0        ;
  497.     Waitblt                ; * Waitblit.
  498.     move.w    d2,BltAptl(a6)        ; * Start to feed the blitter.
  499.     sub.w    d3,d2            ;
  500.     lsl.w    #6,d3            ;
  501.     addq.w    #2,d3            ;
  502.     move.w    d0,BltCon0(a6)        ;
  503.     move.b    oct(PC,d5.w),BltCon1+1(a6)
  504.     move.l    d4,BltCpth(a6)        ;
  505.     move.l    d4,BltDpth(a6)        ;
  506.     movem.w    d1/d2,BltBmod(a6)    ;
  507.     move.w    d3,(a6)            ; * Draw line.
  508. return:    rts                ;
  509. drawfin:cmp.w    #$8000,4(a2)        ; * Finished?
  510.     bne    nxtline            ; * If not, jump back.
  511. drawrgt:cmp.l    #out,a1            ; * Draw lines between right
  512.     beq.s    fillsur            ;   edge-clipped lines.
  513.     move.w    -(a1),d1        ;
  514.     move.w    -(a1),d3        ;
  515.     move.w    screen+2(PC),d0        ;
  516.     move.w    d0,d2            ;
  517.     pea    drawrgt(PC)        ;
  518.     bra    draw            ; * Draw line.
  519. oct:    dc.l    $3431353,$b4b1757    ; * Octant-codes.
  520.  
  521. **************************** FILL THE SURFACE ***************************
  522. fillsur:lea    workscr+44*[Height/2-1]-2,a0; * Get workscreen address.
  523.     movem.w    (SP)+,d0-d3        ; * Get area to be filled.
  524.     cmp.w    #$8000,-2(SP)        ; * Surface in screen?
  525.     beq    nxtsurf            ;
  526.     move.w    d3,d4            ; * Find the address of the
  527.     muls    #44,d4            ;   lower-right corner.
  528.     add.l    d4,a0            ;
  529.     lsr.w    #4,d0            ;
  530.     lsr.w    #4,d2            ;
  531.     addq.w    #1,d2            ;
  532.     add.w    d2,a0            ;
  533.     add.w    d2,a0            ;
  534.            sub.w    d1,d3            ;
  535.     move.l    d2,d1            ; * Save for later use.
  536.     lsl.w    #6,d3            ; * Find the blitsize.
  537.     sub.w    d0,d2            ;
  538.     or.w    d2,d3            ;
  539.     add.w    d2,d2            ; * Find the modulo.
  540.     moveq    #44,d6            ;
  541.     sub.w    d2,d6            ;
  542.     move.w    d6,BltDmod(a6)        ;
  543.     move.l    a0,d5            ;
  544.     Waitblt                ; * Waitblit
  545.     move.l    #$9f00012,BltCon0(a6)    ; * Feed blitter.
  546.     move.w    d6,BltAmod(a6)        ;
  547.     move.l    d5,BltApth(a6)        ;
  548.     move.l    a0,BltDpth(a6)        ;
  549.     move.w    d3,(a6)            ; * Start filling.
  550.  
  551. ****************** COPY THE SURFACE FROM THE WORKSCREEN *****************
  552.     move.w    d6,BltCmod(a6)        ; * Set modulo for source B & C.
  553.     add.w    #132,d6            ;
  554.     move.w    d6,BltBmod(a6)        ;
  555.     move.l    d5,d0            ; * Find start-address for
  556.     add.l    #stencil-workscr+44,d0    ;   source C (mask).
  557.     add.w    d1,d1            ;
  558.     asl.l    #2,d4            ; * Find start-address for
  559.     add.l    regist4+16(PC),d1    ;   destination D.
  560.     add.l    d4,d1            ;
  561.     moveq    #3,d2            ; * Counter=3.
  562.     Waitblt                ; * Waitblit.
  563.     move.w    #2,BltCon1(a6)        ; * Blitter-registers which may
  564.     move.w    d6,BltDmod(a6)        ;   be set only once.
  565. colloop:sub.l    2(a5),d0        ;
  566.     move.l    d1,a0            ;
  567.     Waitblt                ; * Waitblit.
  568.     move.w    (a5)+,BltCon0(a6)    ; * Set correct bltcon0.
  569.     movem.l    d0/d1/d5/a0,BltCpth(a6)    ; * Feed blitter.
  570.     move.w    d3,(a6)            ; * Start copying to plane 1.
  571.     add.l    #44,d1            ; * Next plane.
  572.     add.l    (a5)+,d0        ;
  573.     dbf    d2,colloop        ; * Finished? If not, jump back.
  574.     sub.w    #132,d6            ;
  575.     Waitblt                ; * Waitblit.
  576.     move.w    #$100,BltCon0(a6)    ; * Feed the blitter.
  577.     move.w    d6,BltDmod(a6)        ;
  578.     move.l    d5,BltDpth(a6)        ;
  579.     move.w    d3,(a6)            ; * Start clearing workscreen.
  580.     bra    nxtsurf            ; * Jump to draw next surface.
  581.  
  582. ************************** REGISTERS & ARRAYS ***************************
  583. regist1:dc.l 0,0,0,sinetab,sinetab+512,copper2,matrix+18,matrix,$dff058
  584. regist2:dc.l surfcz1,matrix+18,rot_3d,0,data_2d,data_3d,0
  585. regist3:dc.l lines,surface,surfcz1,connect,data_2d,surfcz2
  586. regist4:dc.l out,surface,surfcz2,$dff058,0,0
  587. matrix:    dc.w 30000,0,0,0,30000,0,0,0,30000,0,0,0,0,0,0,0,0,0
  588. screen:    dc.w -Width/2,Width/2-1,-Height/2,Height/2 ; * (X1,X2,Y1,Y2).
  589. adds:    dc.l sizes,data_3d
  590. ezvec:    dc.w 30,50,50
  591.  
  592. out:    blk.w    32,0
  593. data_2D:blk.w    1024,0
  594. lines:    blk.w    1024,0
  595. surfcz1:blk.w    512,0
  596. surfcz2:blk.w    256,0
  597. surface:blk.w    256,0
  598.  
  599. *********************  V E C T O R - O B J E C T S  *********************
  600. * First word of each surface:                        *
  601. *        BIT    0- 7: Number of visible points in the surface.    *
  602. *        BIT    8-10: Colour of the surface. (1-6)        *
  603. *        BIT      15: 1 = End of object                *
  604. *                                    *
  605. * First 5 words of each animation:                    *
  606. *         1:Speed-counter  2:Speed  3:Point  4:Position  5:Frames    *
  607. *                                    *
  608. *   Negative connect-values (must be set first) give invisible points.    *
  609. *************************************************************************
  610.  
  611.     Include    "df0:Vector/Objects/4bp Objects/Robot.4bp"
  612.